#!/usr/bin/env python

import model
import progressbar
import messaging.sms
import resource.string.app

from .._console import Console

class Decompiler(Console):

    def run(self):
        self.greeting(resource.string.app)
        
        self.progress('Opening database... ')
        db = self.openDb()
        if not db:
            self.fail('Error >_<\n')
        else:
            self.success('OK ^_^v\n')
            self.progress('Loading undecompiled message from database... ')
            inboxes = self.load(db)
            self.info('OK ^_^v\n')
            
            total = len(inboxes)
            self.info('Found {:,} unprocessed PDU in database.\n'.format(total))
            
            if inboxes:
                self.decompile(inboxes)
                if db.dirty:
                    self.progress('Committing changes to database... ')
                    try: db.commit()
                    except: self.fail('Error >_<\n')
                    else: self.success('OK ^_^v\n')
        
        self.info('SMS decompiler finished.\n\n')
        
        self.farewell()

    def load(self, db):
        condition = model.sa.and_(model.Message.decompiled == None)
        query = db.query(model.Message)
        return query.filter(condition).all()
    
    def decompile(self, inboxes):
        if not self._silent:
            total = len(inboxes)
            simple = progressbar.SimpleProgress()
            percentage = progressbar.Percentage()
            bar = progressbar.Bar(marker='#', left='[', right=']')
            eta = progressbar.ETA()
            widgets = ['Decompiling ', simple, ': ', bar, ' ', percentage, ' ',
                       eta]
            progress = progressbar.ProgressBar(widgets=widgets, maxval=total)
            progress.start()
            
        for index, inbox in enumerate(inboxes):
            try:
                deliver = messaging.sms.SmsDeliver(inbox.pdu)
                # Convert content to unicode to raise exception for non text
                message = unicode(deliver.text)
                inbox.decompiled = 1
            except:
                inbox.decompiled = 0
            
            if inbox.decompiled:
                inbox.message = deliver.text
                inbox.sender = deliver.number
                inbox.dateTime = deliver.date
                inbox.total = 1
                inbox.sequence = 1
                if deliver.udh:
                    if deliver.udh.concat:
                        inbox.decompiled = 1
                        inbox.reference = deliver.udh.concat.ref
                        inbox.total = deliver.udh.concat.cnt
                        inbox.sequence = deliver.udh.concat.seq
                    else:
                        headers = deliver.udh.headers
                        for key in headers:
                            try:
                                inbox.reference = headers[key][0]
                                inbox.total = headers[key][1]
                                inbox.sequence = headers[key][2]
                            except:
                                pass
                            else:
                                inbox.decompiled = 1
                            break
            if not self._silent: progress.update(index + 1)
            
        if not self._silent: progress.finish()